#!/usr/bin/env python
"""

   sort_by_embedded_numbers.py


        sort by embedded strings if any. Also means sort by numbers before strings

   # originally called
   natural_sort.py
        submitted by
        David Klaffenbach
        http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/285264

"""


import re
digitsre=re.compile(r'\d+')         # finds groups of digits
D_LEN=15


# each numeric part is left padded with strings to 15 digits
def highlight_embedded_numbers(s):
    '''decorate function for sorting alphanumeric strings naturally'''
    return digitsre.sub(lambda s: str(len(s.group())).zfill(D_LEN)+s.group(),s)


def sorted_by_embedded_numbers(list_):
    return sorted(list_, key=highlight_embedded_numbers)

def _unit_test():
    import json

    #works for simple list
    chrm = list()
    for x in range(22):
        chrm.append(str(x + 1))
    chrm.append("X")
    chrm.append("Y")
    chrm.append("something_longest2a1")
    chrm.append("something_longest1b4")
    chrm.append("something_longest011")
    chrm.reverse()
    assert("".join(sort_by_embedded_numbers(chrm)) == '12345678910111213141516171819202122XYsomething_longest1b4something_longest2a1something_longest011')


    #works for more complicated list of tuple
    chrm = [(i, c) for i, c in enumerate(chrm)]
    chrm = json.dumps(sorted(chrm, key = lambda s:highlight_embedded_numbers(s[1])))
    assert(chrm == '[[26, "1"], [25, "2"], [24, "3"], [23, "4"], [22, "5"], [21, "6"], [20, "7"], [19, "8"], [18, "9"], [17, "10"], [16, "11"], [15, "12"], [14, "13"], [13, "14"], [12, "15"], [11, "16"], [10, "17"], [9, "18"], [8, "19"], [7, "20"], [6, "21"], [5, "22"], [4, "X"], [3, "Y"], [1, "something_longest1b4"], [2, "something_longest2a1"], [0, "something_longest011"]]')


if __name__ == '__main__':
    _unit_test()

